#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef NON_OS

#else
#include <fcntl.h>
#include <unistd.h>
#endif

#include <config.h>

#include <systems.h>
#include <types.h>
#include <gapi.h>
#include <image.h>
#include <misc.h>
#include <font.h>

#ifdef FONT_SUPPORT

int load_font(TEXT *txt, u8 *font)
{
    int i;
    unicode_t *str;
#ifdef FONT_FREETYPE2_SUPPORT
    FT_FONT *ft;
#endif
#ifdef FONT_BDF_SUPPORT
    BDF_FONT *pf;
#endif
    
    if(!txt || !txt->string || !font)
        return -1;
    
    str = txt->string;
    txt->txt_count = uni_strlen(str);
    
    //DPRINTF("Text Count: %d\n", txt->txt_count);
    txt->data = (u8 **)malloc(txt->txt_count * sizeof(u8 *));
    txt->char_width = (u32 *)malloc(txt->txt_count * sizeof(u32));
    txt->char_height = (u32 *)malloc(txt->txt_count * sizeof(u32));
    if(!txt->data || !txt->char_width || !txt->char_height) {
        return -2;
    }
    
#ifdef FONT_BDF_SUPPORT
    pf = bdf_read_font(font);
    if(!pf) {
        return -3; /* Fault to read font file */
    }
    else {
        txt->txt_width = 0;
        txt->txt_height = pf->height;
        for(i = 0; i < txt->txt_count; i++) {
            txt->data[i] = bdf_load_bmp(pf, (int)str[i], txt->bg_color, txt->fg_color);
            txt->char_width[i] = pf->width ? pf->width[(int)str[i] - pf->firstchar] : pf->maxwidth;
            txt->char_height[i] = pf->height;
            txt->txt_width += txt->char_width[i];
            //DPRINTF("txt->data[%d] = %x\n", i, (u32)txt->data[i]);
            if(!txt->data[i])
                WARNING("Failed loading font bmp (Unicode: %x)\n", str[i]);
        }
        if(txt->char_height[0] != txt->size) {
            WARNING("Text size mismatch, use font default size: %d\n", txt->char_height[0]);
            txt->size = txt->char_height[0];
        }
        bdf_free_font(pf);
        return 0;
    }

#endif
#ifdef FONT_FREETYPE2_SUPPORT
    ft = freetype2_get_face(font);
    if(!ft) {
        ft = freetype2_add_face(font, txt->font_size);
        if(!ft) {
            return -3;
        }
    }
    
    txt->txt_width = 0;
    for(i = 0; i < txt->txt_count; i++) {
        txt->data[i] = freetype2_load_bmp(ft, str[i], txt->size, txt->bg_color, txt->fg_color);
        if(!txt->data[i])
            WARNING("Failed loading font bmp (Unicode: %x)\n", str[i]);
        txt->char_width[i] = ft->width;
        txt->char_height[i] = ft->height;
        txt->txt_width += txt->char_width[i];
    }
    txt->txt_height = txt->char_height[0];
    return 0;
#endif
        return -4; /* Font format not support */
}



int reload_font(TEXT *txt, unicode_t *new_string)
{
    int i;
    int new_txt_count;
    char *suf;
#ifdef FONT_FREETYPE2_SUPPORT
    FT_FONT *ft;
#endif
#ifdef FONT_BDF_SUPPORT
    BDF_FONT *pf;
#endif
    
    if(!txt || !new_string)
        return -1;
    
    new_txt_count = uni_strlen(new_string);
    suf = _suffix(txt->font_file);
    
    //DPRINTF("Text Count: %d\n", txt->txt_count);
    if(txt->txt_count > new_txt_count) {
        for(i = new_txt_count; i < txt->txt_count; i++) {
            if(txt->data[i])
                free(txt->data[i]);
        }
    }
    txt->data = (u8 **)realloc(txt->data, new_txt_count * sizeof(u8 *));
    txt->char_width = (u32 *)realloc(txt->char_width, new_txt_count * sizeof(u32));
    txt->char_height = (u32 *)realloc(txt->char_height, new_txt_count * sizeof(u32));
    if(!txt->data || !txt->char_width || !txt->char_height) {
        return -2;
    }
    
#ifdef FONT_BDF_SUPPORT
    pf = bdf_read_font(font);
    if(!pf) {
        return -3; /* Fault to read font file */
    }
    else {
        txt->txt_width = 0;
        txt->txt_height = pf->height;
        for(i = 0; i < new_txt_count; i++) {
            if(i < txt->txt_count) {
                if(!memcmp(&txt->string[i], &new_string[i], sizeof(unicode_t))) {
                    /* The same as previous text */
                    txt->txt_width += txt->char_width[i];
                    continue;
                }
                else {
                    free(txt->data[i]);
                    free(txt->char_width[i]);
                    free(txt->char_height[i]);
                }
            }
            txt->data[i] = bdf_load_bmp(pf, (u32)new_string[i], txt->bg_color, txt->fg_color);
            txt->char_width[i] = pf->width ? pf->width[(int)new_string[i] - pf->firstchar] : pf->maxwidth;
            txt->char_height[i] = pf->height;
            txt->txt_width += txt->char_width[i];
            //DPRINTF("txt->data[%d] = %x\n", i, (u32)txt->data[i]);
            if(!txt->data[i])
                WARNING("Failed loading font bmp (Unicode: %x)\n", new_string[i]);
        }
        if(txt->char_height[0] != txt->size) {
            WARNING("Text size mismatch, use font default size: %d\n", txt->char_height[0]);
            txt->size = txt->char_height[0];
        }
        bdf_free_font(pf);
        txt->txt_count = new_txt_count;
        return 0;
    }
#endif
#ifdef FONT_FREETYPE2_SUPPORT
    ft = freetype2_get_face(txt->font_file);
    if(!ft) {
        ft = freetype2_add_face(txt->font_file, txt->font_size);
        if(!ft) {
            return -3;
        }
    }
    else {
        txt->txt_width = 0;
        for(i = 0; i < new_txt_count; i++) {
            if(i < txt->txt_count) {
                if(txt->bg_color == pCOLOR_TRANSPARENT && 
                   !memcmp(&txt->string[i], &new_string[i], sizeof(unicode_t))) {
                    /* The same as previous text */
                    //DPRINTF("Same as previous text\n");
                    txt->txt_width += txt->char_width[i];
                    continue;
                }
                else {
                    free(txt->data[i]);
                }
            }
            /* Reload char data[i] */
            txt->data[i] = freetype2_load_bmp(ft, (u32)new_string[i], txt->size, txt->bg_color, txt->fg_color);
            if(!txt->data[i])
                WARNING("Failed loading font bmp (Unicode: %x)\n", new_string[i]);
            txt->char_width[i] = ft->width;
            txt->char_height[i] = ft->height;
            txt->txt_width += txt->char_width[i];
        }
        txt->txt_height = txt->char_height[0];
        //freetype2_free(ft);
        txt->txt_count = new_txt_count;
        return 0;
    }
#endif

    return -4; /* Font format not support */
}


int free_font(TEXT *txt)
{
    int i;
    
    if(!txt)
        return -1;
        
    if(txt->txt_count == 0)
        return 0;
        
    if(txt->data && txt->char_width && txt->char_height) {
        for(i = 0; i < txt->txt_count; i++) {
            if(txt->data[i])
                free(txt->data[i]);
        }
        free(txt->data);
        free(txt->char_width);
        free(txt->char_height);
        txt->data = NULL;
        txt->char_width = NULL;
        txt->char_height = NULL;
    }
    else {
        ERROR("Font data broken!\n");
        return -2;
    }
    txt->txt_width = 0;
    txt->txt_height = 0;
    txt->txt_count = 0;
    if(txt->string) {
        free(txt->string);
        txt->string = NULL;
    }
    
    /* FIXME: find a good timing to call freetype2_free(ft) */
    return 0;
}

#endif /* FONT_SUPPORT */
